# ============================================================================
# GPU Performance Analysis - Complete Timing Breakdown
# Shows exactly where GPU computation time is spent vs CPU
# ============================================================================

wipe
puts "GPU vs CPU Performance Analysis with Detailed Timing Breakdown"

# ============================================================================
# Test Model Configuration
# ============================================================================

model basic -ndm 2 -ndf 2

# Medium-sized model for meaningful GPU vs CPU comparison
set nEleX 300
set nEleY 200
set dx 1.0
set dy 1.0

puts "Creating test model: ${nEleX}x${nEleY} = [expr $nEleX*$nEleY] elements"

# Create nodes
set nodeTag 1
for {set j 0} {$j <= $nEleY} {incr j} {
    for {set i 0} {$i <= $nEleX} {incr i} {
        node $nodeTag [expr $i * $dx] [expr $j * $dy]
        incr nodeTag
    }
}

# Material and elements
nDMaterial ElasticIsotropic 1 50.0e6 0.3 1800.0

set eleTag 1
for {set j 0} {$j < $nEleY} {incr j} {
    for {set i 0} {$i < $nEleX} {incr i} {
        set n1 [expr $j*($nEleX+1) + $i + 1]
        set n2 [expr $j*($nEleX+1) + $i + 2]
        set n3 [expr ($j+1)*($nEleX+1) + $i + 2]
        set n4 [expr ($j+1)*($nEleX+1) + $i + 1]
        element quad $eleTag $n1 $n2 $n3 $n4 1.0 "PlaneStrain" 1
        incr eleTag
    }
}

# Boundary conditions
for {set i 1} {$i <= [expr $nEleX+1]} {incr i} {
    fix $i 1 1
}

# Loading
pattern Plain 1 Linear {
    for {set i 1} {$i <= [expr $nEleX+1]} {incr i} {
        set topNode [expr $nEleY*($nEleX+1) + $i]
        load $topNode 0.0 -1000.0
    }
}

puts "Model: [expr $nEleX*$nEleY] elements, [expr ($nEleX+1)*($nEleY+1)*2] DOFs"

# ============================================================================
# CPU Performance Test
# ============================================================================

puts "\n=== CPU PERFORMANCE TEST ==="

constraints Plain
numberer Plain
system BandGeneral
test NormDispIncr 1.0e-6 25
algorithm Newton
integrator LoadControl 0.1
analysis Static

set cpuTotalTime 0
set testSteps 10

puts "Running CPU analysis ($testSteps steps)..."

for {set i 1} {$i <= $testSteps} {incr i} {
    set stepStart [clock clicks -milliseconds]
    set ok [analyze 1]
    set stepEnd [clock clicks -milliseconds]
    set stepTime [expr $stepEnd - $stepStart]
    set cpuTotalTime [expr $cpuTotalTime + $stepTime]
    
    if {$i % 5 == 0} {
        puts "  CPU step $i: ${stepTime} ms"
    }
    
    if {$ok != 0} {
        puts "CPU analysis failed at step $i"
        break
    }
}

set cpuAvgTime [expr $cpuTotalTime / $testSteps]
puts "CPU Results: Total=${cpuTotalTime}ms, Average=${cpuAvgTime}ms per step"

wipeAnalysis

# ============================================================================
# GPU Performance Test with Detailed Breakdown
# ============================================================================

puts "\n=== GPU PERFORMANCE TEST WITH DETAILED TIMING ==="

constraints Plain
numberer Plain
system GPUSolver
test NormDispIncr 1.0e-6 25
algorithm Newton
integrator LoadControl 0.1
analysis Static

set gpuTotalTime 0

puts "Running GPU analysis ($testSteps steps)..."
puts "Watch for detailed GPU timing breakdown below:"
puts ""

for {set i 1} {$i <= $testSteps} {incr i} {
    puts "--- GPU Step $i ---"
    set stepStart [clock clicks -milliseconds]
    set ok [analyze 1]
    set stepEnd [clock clicks -milliseconds]
    set stepTime [expr $stepEnd - $stepStart]
    set gpuTotalTime [expr $gpuTotalTime + $stepTime]
    
    puts "GPU step $i: ${stepTime} ms (wall time)"
    puts "^^ GPU timing details should appear above ^^"
    puts ""
    
    if {$ok != 0} {
        puts "GPU analysis failed at step $i"
        break
    }
}

set gpuAvgTime [expr $gpuTotalTime / $testSteps]
puts "GPU Results: Total=${gpuTotalTime}ms, Average=${gpuAvgTime}ms per step"

# ============================================================================
# Performance Comparison and Analysis
# ============================================================================

puts "\n" 
puts "=========================================="
puts "PERFORMANCE COMPARISON RESULTS"
puts "=========================================="
puts "Model: [expr $nEleX*$nEleY] elements, [expr ($nEleX+1)*($nEleY+1)*2] DOFs"
puts "Test steps: $testSteps"
puts ""
puts "CPU Performance:"
puts "  Total time: ${cpuTotalTime} ms"
puts "  Average per step: ${cpuAvgTime} ms"
puts ""
puts "GPU Performance:" 
puts "  Total time: ${gpuTotalTime} ms"
puts "  Average per step: ${gpuAvgTime} ms"
puts ""

if {$cpuTotalTime > 0 && $gpuTotalTime > 0} {
    set speedup [expr double($cpuTotalTime) / $gpuTotalTime]
    puts "Performance Analysis:"
    if {$speedup > 1.0} {
        puts "  ✓ GPU SPEEDUP: [format %.2fx $speedup] faster than CPU"
        puts "  ✓ Time saved: [expr $cpuTotalTime - $gpuTotalTime] ms ([format %.1f [expr ($cpuTotalTime-$gpuTotalTime)*100.0/$cpuTotalTime]]%)"
    } else {
        set slowdown [expr double($gpuTotalTime) / $cpuTotalTime]
        puts "  ✗ GPU SLOWDOWN: [format %.2fx $slowdown] slower than CPU" 
        puts "  ✗ Extra time: [expr $gpuTotalTime - $cpuTotalTime] ms"
    }
}

puts ""
puts "=========================================="
puts "GPU TIMING BREAKDOWN ANALYSIS"
puts "=========================================="
puts "Above in the GPU test output, you should see:"
puts ""
puts "GPU Performance Timing Statistics:"
puts "  Total Solve: Total=X.XXs, Calls=N, Avg=X.XXs, Percentage=XX%"
puts "  Memory Transfer: Total=X.XXs, Calls=N, Avg=X.XXs, Percentage=XX%"
puts "  GPU Computation: Total=X.XXs, Calls=N, Avg=X.XXs, Percentage=XX%"
puts "  Matrix Assembly: Total=X.XXs, Calls=N, Avg=X.XXs, Percentage=XX%"
puts "  Data Synchronization: Total=X.XXs, Calls=N, Avg=X.XXs, Percentage=XX%"
puts ""
puts "INTERPRETATION GUIDE:"
puts "• Memory Transfer > 50% → Memory bandwidth bottleneck"
puts "• GPU Computation < 30% → GPU underutilized"  
puts "• Matrix Assembly > 60% → Assembly needs optimization"
puts "• Data Sync > 30% → Too much CPU-GPU communication"
puts ""
puts "RECOMMENDATIONS:"
if {$speedup < 1.0} {
    puts "GPU is slower than CPU. Possible reasons:"
    puts "• Problem size too small (try 1000+ elements)"
    puts "• GPU overhead dominates for this scale"
    puts "• Memory transfer costs > computation benefits"
    puts "• GPU matrix assembly not fully optimized"
}
puts "• Use nvidia-smi during analysis to check GPU utilization"
puts "• Increase problem size for better GPU efficiency"
puts "• Check GPU memory usage and bandwidth utilization"

puts ""
puts "=========================================="
puts "Performance analysis complete!"
puts "Check the GPU timing breakdown above to see exactly"
puts "where computation time is being spent."
puts "=========================================="